package extras.salvation.api.methods;

import java.util.Arrays;

import com.rsbuddy.script.wrappers.Item;
import com.rsbuddy.script.wrappers.Npc;
import com.rsbuddy.script.wrappers.Player;

/**
 * @author Salvation
 * @version 1.0
 * @since 20-08-2011
 */
public final class ExtendedArrays {

	/**
	 * @author Salvation
	 * @param array The array to check.
	 * @param value The value to check.
	 * @param partially <tt>true</tt> if you wish to use array[index].contains(value); <tt>false</tt> if you wish to use array[index].equals(value).
	 * @return <tt>true</tt> if and only if the criteria matched and the value was found within the array.
	 */
	public static boolean contains(final String[] array, final String value, final boolean partially) {
		if (array == null || value == null) return false;
		for (String s : array) {
			s = s.toLowerCase();
			if (partially && s.contains(value)) {
				return true;
			} else if (!partially && s.equals(value)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @author Salvation
	 * @param array The array to check.
	 * @param value The value to check.
	 * @return <tt>true</tt> if the value was found within the array.
	 * @see containsOneOf()
	 * @see containsAllOf()
	 */
	public static boolean contains(final int[] array, final int value) {
		if (array == null) return false;
		for (final int i : array) {
			if (i == value) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @author Salvation
	 * @param array The array to check.
	 * @param values The values to check.
	 * @return <tt>true</tt> if at least one of the values were found within the array.
	 * @see contains()
	 * @see containsAllOf()
	 */
	public static boolean containsOneOf(final int[] array, final int[] values) {
		if (array == null || values == null) return false;
		for (final int i : values) {
			if (contains(array, i)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @author Salvation
	 * @param array The array to check.
	 * @param values The values to check.
	 * @return <tt>true</tt> if all values were found within the array.
	 * @see contains()
	 * @see containsOneOf()
	 */
	public static boolean containsAllOf(final int[] array, final int[] values) {
		if (array == null || values == null) return false;
		int matches = 0;
		for (final int i : values) {
			if (contains(array, i)) {
				matches++;
			}
		}
		return matches == values.length;
	}

	/**
	 * @author Salvation
	 * @param array The array to add the value to.
	 * @param value The value to be added to the array.
	 * @return The array including the new value.
	 */
	public static String[] add(final String[] array, final String value) {
		if (array == null) return new String[]{value};
		String[] s = Arrays.copyOf(array, array.length + 1);
		s[s.length - 1] = value;
		return s;
	}

	/**
	 * @author Salvation
	 * @param array The array to add the value to.
	 * @param value The value to be added to the array.
	 * @return The array including the new value.
	 */
	public static int[] add(final int[] array, final int value) {
		if (array == null) return new int[]{value};
		int[] i = Arrays.copyOf(array, array.length + 1);
		i[i.length -1] = value;
		return i;
	}

	/**
	 * @author Salvation
	 * @param array The array to add the value to.
	 * @param value The value to be added to the array.
	 * @return The array including the new value.
	 */
	public static Player[] add(final Player[] array, final Player value) {
		if (array == null) return new Player[]{value};
		Player[] p = Arrays.copyOf(array, array.length + 1);
		p[p.length - 1] = value;
		return p;
	}

	/**
	 * @author Salvation
	 * @param array The array to add the value to.
	 * @param value The value to be added to the array.
	 * @return The array including the new value.
	 */
	public static Npc[] add(final Npc[] array, final Npc value) {
		if (array == null) return new Npc[]{value};
		Npc[] n = Arrays.copyOf(array, array.length + 1);
		n[n.length - 1] = value;
		return n;
	}

	/**
	 * @author Salvation
	 * @param array The array to add the value to.
	 * @param value The value to be added to the array.
	 * @return The array including the new value.
	 */
	public static Item[] add(final Item[] array, final Item value) {
		if (array == null) return new Item[]{value};
		Item[] i = Arrays.copyOf(array, array.length + 1);
		i[i.length - 1] = value;
		return i;
	}

	/**
	 * @author Salvation
	 * @param array The array to add the value to.
	 * @param value The value to be added to the array.
	 * @return The array including the new value.
	 */
	public static Object[][] add(final Object[][] array, final Object[] value) {
		if (array == null) return new Object[][]{value};
		Object[][] o = Arrays.copyOf(array, array.length + 1);
		o[o.length -1] = value;
		return o;
	}

	/**
	 * @author Salvation
	 * @param array The two-dimensional Object array.
	 * @param index The index to be removed from the array.
	 * @return The array without the index. All indices after the index will shift.
	 */
	public static Object[][] remove(final Object[][] array, final int index) {
		if (array == null) return null;
		Object[][] o = new Object[array.length - 1][];
		for (int i = 0; i < o.length; i++) {
			o[i] = array[i - (i >= index ? 1 : 0)];
		}
		return o;
	}
}